﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Practices.Unity;

using ERPStore.Extensions;
using System.Configuration;
using Microsoft.Practices.Unity.Configuration;

namespace ERPStore.Host.Start
{
	public class UnityConfig
	{
		private static string m_Path;

		private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
		{
			var container = ERPStore.GlobalConfiguration.Configuration.DependencyResolver.GetContainer();

			var debugEnabled = Convert.ToBoolean(ERPStore.Configuration.ConfigurationSettings.AppSettings["debugEnabled"] ?? "false");

			ERPStore.GlobalConfiguration.Configuration.HosterName = ERPStore.Configuration.ConfigurationSettings.AppSettings["ERStoreHostName"] ?? "SvcHost";
			ERPStore.GlobalConfiguration.Configuration.ExecutingContext = Models.ExecutingContext.Production;
			ERPStore.GlobalConfiguration.Configuration.DebugEnabled = debugEnabled;

			container.RegisterType<ERPStore.Logging.ILogger, Logging.PushLogger>();

			LoadConfigurationOverrides(container);
			return container;
		});

		public static IUnityContainer GetConfiguredContainer(string location)
		{
			m_Path = location;
			Console.WriteLine("Root path : {0}", location);
			return container.Value;
		}

		private static void LoadConfigurationOverrides(IUnityContainer container)
		{
			ERPStore.GlobalConfiguration.Configuration.Logger.Info("Load unity configuration");

			// Chargement des services et overriding a partir du fichier
			// de configuration unity.config
			var map = new ExeConfigurationFileMap();
			map.ExeConfigFilename = System.IO.Path.Combine(m_Path, "unity.config");
			var config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
			var section = (UnityConfigurationSection)config.GetSection("unity");
			if (section == null)
			{
				ERPStore.GlobalConfiguration.Configuration.Logger.Info("No unity configuration section found");
				return;
			}

			try
			{
				section.Configure(container);
				Console.WriteLine("Configuration overrided");
			}
			catch (Exception ex)
			{
				var registrations = section.Containers[0].Registrations;
				// Check du mapping dans le fichier de config
				var fileNameList = registrations.Select(i => i.TypeName.Split(',')[1].Trim()).Distinct();
				foreach (var fileName in fileNameList)
				{
					var f = System.IO.Path.Combine(m_Path, fileName + ".dll");
					if (System.IO.File.Exists(f))
					{
						continue;
					}
					f = System.IO.Path.Combine(m_Path, "bin", fileName + ".dll");
					if (System.IO.File.Exists(f))
					{
						continue;
					}

					throw new System.IO.FileNotFoundException("File does not exists : " + f);
				}

				var message = string.Empty;
				foreach (var typeEntry in registrations)
				{
					Type fromType, toType;

					try
					{
						fromType = Type.GetType(typeEntry.TypeName, true);
						message = message + "FromType : " + typeEntry.TypeName + "\r\n";
					}
					catch
					{
						throw new Exception("Could not create the contract type: " + typeEntry.TypeName);
					}

					try
					{
						toType = Type.GetType(typeEntry.MapToName, true);
						message = message + "ToType : " + typeEntry.MapToName + "\r\n";
					}
					catch
					{
						throw new Exception("Could not create the mapped type: " + typeEntry.MapToName);
					}
				}

				throw new Exception("unity.config failed : " + message);
			}
		}

	}
}
